﻿using System;
using System.ServiceModel;
using System.Transactions;
using VideoStore.Business.Facade;
using VideoStore.Common.Enum;
using VideoStore.Domain.Entities;
using VideoStore.Services.DeliveryServiceReference;
using VideoStore.Services.Dto;
using VideoStore.Services.Interface;
using VideoStore.Common.Response;
using VideoStore.Common.Response.Extension;
using VideoStore.Services.Translation;
using VideoStore.Services.Translation.Base;
using VideoStore.Services.Translation.Factory;

namespace VideoStore.Services
{
    public class OrderService : IOrderService
    {
        #region Implementation of IOrderService

        /// <summary>
        /// Gets the order by id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public Response<OrderDto> GetOrderById(Guid id)
        {
            var response = new Response<OrderDto>();
            response.IsSuccessful = true;
            try
            {
                var facade = VideoStoreFacade.Instance;
                Order order = facade.GetOrderById(id);
                ITranslator translator = TranslatorFactory.GetTranslatorByType(typeof(OrderTranslator));
                response.ResponseObject = translator.TranslateToDto<Order, OrderDto>(order);
            }
            catch (Exception ex)
            {
                response.IsSuccessful = false;
                response.Errors.AddFatalError(ex.Message);
            }
            return response;
        }

        /// <summary>
        /// Creates the order.
        /// </summary>
        /// <param name="newOrder">The new order.</param>
        /// <returns></returns>
        public Response<OrderDto> CreateOrder(OrderDto newOrder)
        {
            var response = new Response<OrderDto>();
            response.IsSuccessful = true;
            try
            {
                var facade = VideoStoreFacade.Instance;
                ITranslator translator = TranslatorFactory.GetTranslatorByType(typeof(OrderTranslator));
                Order orderEntity = translator.TranslateToEntity<OrderDto, Order>(newOrder);
                Order savedOrder = facade.CreateOrder(orderEntity);
                response.ResponseObject = translator.TranslateToDto<Order, OrderDto>(savedOrder);
                response.Messages.AddSuccessfulSaveMessage("Order");
            }
            catch (Exception ex)
            {
                response.IsSuccessful = false;
                response.Errors.AddFatalError(ex.Message);
            }
            return response;
        }

        /// <summary>
        /// Submits the order.
        /// </summary>
        /// <param name="orderId">The order id.</param>
        /// <returns></returns>
        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
        public Response<OrderDto> SubmitOrder(Guid orderId)
        {
            var response = new Response<OrderDto>();
            response.IsSuccessful = true;
            try
            {
                Console.WriteLine("Got Order Id {0}", orderId);
                var facade = VideoStoreFacade.Instance;
                var orderEntity = facade.GetOrderById(orderId);
                bool canSubmitOrder = facade.CanSubmitOrder(orderEntity);
                if (!canSubmitOrder)
                {
                    response.Errors.Add(new Error("Order already submitted."));
                    response.IsSuccessful = false;
                }
                else
                {
                    using (var scope = new TransactionScope(TransactionScopeOption.Required))
                    {
                        var deliveryProxy = new DeliveryServiceQueuedClient();
                        deliveryProxy.Open();
                        var deliveryDto = new DeliveryDto();
                        deliveryDto.Id = Guid.NewGuid();
                        deliveryDto.DeliveryDate = DateTime.Now;
                        deliveryDto.OrderId = orderEntity.id;
                        deliveryDto.Status = DeliveryStatus.Submitted;
                        deliveryDto.WareHouseId = orderEntity.warehouse_id;
                        Console.WriteLine("Submitting request for Delivery Id {0}", deliveryDto.Id);
                        deliveryProxy.SubmitDelivery(deliveryDto);
                        deliveryProxy.Close();
                        scope.Complete();
                    }
                    response.Messages.AddSuccessfulSaveMessage("Order");
                }
            }
            catch (Exception ex)
            {
                response.IsSuccessful = false;
                response.Errors.AddFatalError(ex.Message);
            }
            return response;
        }

        #endregion
    }
}
